#include "udpcksum.h"
#include <bits/getopt_core.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pcap/pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <unistd.h>

struct sockaddr * dest, * local;
struct sockaddr_in locallookup;
socklen_t destlen, locallen;

int datalink;
char * device;
pcap_t * pd;

int rawfd;
int snaplen = 200;
int verbose;
int zerosum;

static void usage(const char * message) {
	
	printf("%s.\n", message);
}

int main(int argc, char * argv[]) {

	int c, lopt = 0;
	char * ptr, localname[1024], * localport;
	struct addrinfo * aip;

	opterr = 0;
	while((c = getopt(argc, argv, "0i:l:v")) != -1) {
		switch (c) {
		case '0':
			zerosum = 1;
			break;	
		case 'i':
			device = optarg;
			break;
		case 'l':
			if ((ptr = strchr(optarg, '.')) == NULL) {
				usage("invalid -1 option");
			}
			*ptr++ = 0;
			localport = ptr;
			strncpy(localname, optarg, sizeof(localname));
			lopt = 1;
			break;
		case 'v':
			verbose = 1;
			break;
		case '?':
			usage("unrecognized option");
		}
	}
	if (optind != argc - 2) {

		usage("missing <host> and/or <server>");
	}
	struct addrinfo hints;
	bzero(&hints, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_DGRAM;
	getaddrinfo(argv[optind], argv[optind + 1], &hints, &aip);
	dest = aip->ai_addr;
	destlen = aip->ai_addrlen;	
	if (lopt) {

		getaddrinfo(localname, localport,&hints, &aip);
		local = aip->ai_addr;
		locallen = aip->ai_addrlen;
	}
	else {

		int s;
		s = socket(AF_INET, SOCK_DGRAM, 0);
		int result = connect(s, (struct sockaddr*)dest, destlen);
		if (result != 0) {
			
			printf("connect failure\n");
			return EXIT_FAILURE;
		}
		locallen = sizeof(locallookup);
		local = (struct sockaddr *)&locallookup;
		getsockname(s, local, &locallen);
		if (locallookup.sin_addr.s_addr == htonl(INADDR_ANY)) {
			printf("Can not determine local address - use -l.\n");			
		}
		close(s);
	}
	open_output();
	open_pcap();
	setuid(getuid());
	// signal process function
	signal(SIGTERM, cleanup);
	signal(SIGINT,  cleanup);
	signal(SIGHUP,  cleanup);
	// 
	test_udp();
	cleanup(0);
	return EXIT_SUCCESS;
}
